/** ==================================================================================== **/
/** 					Definizione dei Model per la gestione della mappa.  			 **/
/** ==================================================================================== **/

/**
 * NOTA: 
 *   To define an instantiatable class / constructor, we can
 *   use either the Factory() of the Value() method.
 *   the Factory since it allows for dependency injection.
 */

/********************************************************/
/*                                                      */
/*         Class Map Options e default                  */
/*                                                      */
/********************************************************/  

/** 
 * Model di configurazione dei layer di base da aggiungere di default alla mappa.
 */
BootApplication.factory("BasicLayerInfo", function() {
	
	/** 
	 * Define the constructor function. 
	 */
    function BasicLayerInfo() {
        /* Roads without additional imagery. */
    	this.hasBingRoad = true,
    	/* Aerial imagery */
    	this.hasBingAerial = true,
    	/* Aerial imagery with a road overlay. */
    	this.hasBingAerialWithLabels = true,	
    	/* */
    	this.hasOpenStreetMap = true,
    	/* */
    	this.hasOsmLigth = true,
    	/* displays Google Earth satellite images */
    	this.hasGoogleSat = false,
    	/* displays a physical map based on terrain information) */
    	this.hasGoogleTerrain = false,
    	/* displays a mixture of normal and satellite views */
    	this.hasGoogleHybrid = false,
    	/* displays the default road map view */
    	this.hasGoogleRoadmap = false,
    	/* vuoto */
    	this.hasBlank = true
    }
    
    /**
     * Define the "instance" methods using the prototype and standard prototypal inheritance.
     */
    BasicLayerInfo.prototype = {
    	isBingRoad: function() { return( this.hasBingRoad ); },
    	isBingAerial: function() { return( this.hasBingAerial ); },
    	isBingAerialWithLabels: function() { return( this.hasBingAerialWithLabels ); },
    	isOpenStreetMap: function() { return( this.hasOpenStreetMap ); },
    	isOsmLigth: function() { return( this.hasOsmLigth ); },
    	isGoogleSat: function() { return( this.hasGoogleSat ); },
    	isGoogleTerrain: function() { return( this.hasGoogleTerrain ); },
    	isGoogleHybrid: function() { return( this.hasGoogleHybrid ); },
    	isGoogleRoadmap: function() { return( this.hasGoogleRoadmap ); },
    	isBlank: function() { return( this.hasBlank ); }
    };
    /**
	 * Return the constructor function
	 */
    return BasicLayerInfo;
});

/** 
 * Model contenente le impostazioni di configurazione di default della mappa
 */
BootApplication.factory("BasicMapOptions", function(BasicLayerInfo) {
	
	/** 
	 * Define the constructor function. 
	 */
    function BasicMapOptions() {
    	/** La projection con la quale l'entità sono gestite. **/
    	this.sourceProjection = "EPSG:4326",
		/** La projection con la quale l'entità sono disegnate in mappa. **/
    	this.destProjection = "EPSG:3857",
		/** Nella misura in cui vincola il centro, in altre parole, il centro non può essere impostato fuori misura. **/
    	this.extent = [8.8103, 45.3213, 9.5080, 45.6006],
		/** Array[lon, lat] rappresentanti la coordinata sulla quale centrare la mappa **/
    	this.center = [16.621036,40.984266],
		/** Identificativo dell'elemento (div) in cui disegnare la mappa **/
    	this.targetMap = null,
		/** 
		 * Url del servizio che restituisce il json con il quale disegnare l'albero(Categoria e sottocategoria). 
		 * L'url che mi aspetto prende come parametri d'ingresso l'id profilo e l'id mappa necessariamente.
	     * In generale, questi parametri li passo all'url facendo il replace delle sequenti stringhe:
	     *   - {value1} per l'id profilo.
	     *   - {value2} per l'id mappa.
	     * 
	     * Es url = "/getTreeCategoria.json/{value1}/{value2}"
		 */
    	this.treeUrl = null,
		/** 
		 * Url del servizio che restituisce il json con l'elenco dei layer da aggiungere alla mappa. 
		 * L'url che mi aspetto prende come parametri d'ingresso l'id profilo e l'id mappa necessariamente.
	     * In generale, questi parametri li passo all'url facendo il replace delle sequenti stringhe:
	     *   - {value1} per l'id profilo.
	     *   - {value2} per l'id mappa.
		 */
    	this.layerUrl = null,
		/** 
		 * Url del servizio che restituisce il json con l'elenco degli stili con cui rappresentare i layer su mappa. 
		 * L'url che mi aspetto prende come parametri d'ingresso l'id profilo e l'id mappa necessariamente.
	     * In generale, questi parametri li passo all'url facendo il replace delle sequenti stringhe:
	     *   - {value1} per l'id profilo.
	     *   - {value2} per l'id mappa.
		 */
    	this.layerStyleUrl = null,
		/** Individua se e quali layer aggiungere di default alla mappa. **/
    	this.basicLayers = new BasicLayerInfo(),
		/** Livello di zoom utilizzato per calcolare la risoluzione iniziale per la visualizzazione. **/
    	this.zoom = 1,
		/** Il livello di zoom minimo utilizzato. **/
    	this.minZoom = 4,
		/** Il livello di zoom massimo utilizzato. **/
    	this.maxZoom = 20,
		/** Risoluzione minima **/
//		this.minResolution = null,
		/** Risoluzione massima **/
//		this.maxResolution = null,
		/** Indica il livello di zoom al quale portare la mappa quando viene geolocalizzata la posizione dell'utente. **/
    	this.geolocateZoom = 16,
		/** Opzione per mostrare tutti gli attributi associati con le fonti di livello nella mappa. **/
    	this.enableAttribution = false,
		/** Opzione per abilitare la rotazione della mappa e il pulsante per ripristinare la rotazione a 0. **/
    	this.enableRotation = false,
		/** Opzione per abilitare lo zoom in e lo zoom out. **/
    	this.enableZoom = true,
		/** Opzione che fornisce un pulsante per attivare o disattivare la mappa in modalità a schermo intero. **/
    	this.enableFullscreen = false,
		/** Un controllo per mostrare le coordinate 2D del cursore del mouse. **/
    	this.enableMousePosition = false,
		/** Un controllo con 2 pulsanti, uno per lo zoom in e una per lo zoom out e lo slider centrale per spostarsi direttamente ad un certo livello di zoom. **/
    	this.enableZoomSlider = false,
		/** Un controllo pulsante che, se premuto, cambia la visualizzazione della mappa in misura specifica. **/
    	this.enableZoomToExtent = false,
		/** Un controllo pulsante che, se premuto, attiva/disattiva la visualizzazione della mappa in 3D/2D. **/
    	this.enable3D = false,
    	/** 
		 * Il controllo LayerSwitcher visualizza una tabella di contenuti per la mappa. In questo modo l'utente può per i layer di Base passare da un
		 * BaseLayers ad un'altro.
		 * Mentre, per i layer non di base, mostrare o nascondere i livelli e consentirne il riordino. 
		 * Per impostazione predefinita, lo switcher è mostrato minimizzato sul bordo destro della mappa, l'utente può espandere cliccando sulla maniglia.
		 */
		this.enableLayerSwitcher = false,
		/** Un controllo pulsante che, se premuto, attiva/disattiva la visualizzazione dell'albero dei layer **/
    	this.enableLayersTree = false,
		/** Un controllo pulsante che, se premuto, viene individuata la posizione di un utente. **/
    	this.enableGeolocation = false,
		/** Creare un nuovo controllo con una mappa in qualità di una mappa panoramica per un'altra mappa definita. **/
    	this.enableOverviewMap = false,
		/** Un controllo che visualizza distanze x assi grezze, calcolato per il centro della finestra. **/
    	this.enableScaleLine = false,
		/** Un controllo per misurare la lunghezza dell'arco tracciato. **/
    	this.enableMeasureLength = false,
		/** Un controllo per misurare la grandezza della superficie tracciata. **/
		this.enableMeasureArea = false,
		/** Un controllo per misurare l'angolo del cerchio tracciato e la larghezza del diametro. **/
		this.enableMeasureAzimut = false,
		/** Un controllo per disegnare la geometria di punti, linestring e poligoni sulla mappa **/
		this.enableDrawGeometry = false,
		/** 
		 * Identificativo dell'elemento da visualizzare a schermo intero. Quando non è previsto, sarà l'elemento che contiene la mappa viewport 
		 * ad essere visualizzato a schermo intero. 
		 */
		this.fullscreenSourceId = 'innerMap',
		/** 
		 * Identificativo dell'elemento HTML in cui openalyer inserirà i controlli che la libreria mette a disposizione. 
		 * (Es: zoomExtent, fullscreen, 3D, geoLocate, measureLength, measureArea, measureAzimut )
		 */
		this.controlTargetId = 'olToolGis',
		/**
		 * Determina se aggiungere ai controlli di Openlayer oltre l'icona, già prevista, anche una label testuale.
		 * (Es: zoomExtent, fullscreen, 3D, geoLocate, measureLength, measureArea, measureAzimut )
		 */
		this.advancedControlHasLabel = true,
		/** Array contenente le tipologie di geometrie che si possono disegnare e modificare sulla mappa **/
		this.geometryType = [ol.interaction.GeometryType.POINT, ol.interaction.GeometryType.LINE_STRING, ol.interaction.GeometryType.POLYGON, ol.interaction.GeometryType.CIRCLE],
		/** Funzione di callback richiamata alla pressione del tasto Salva della geometria disegnata **/
		this.saveGeometryCallback = null,
		/** Funzione di callback richiamata alla pressione del tasto Cancella della geometria disegnata **/
		this.cancelGeometryCallback = null,
		/** Identificativo del profilo della mappa (Entrambi determinabili consultando l'interfaccia di gestione mappe) **/
		this.profiloId = null,
		/** Identificativo della mappa (Entrambi determinabili consultando l'interfaccia di gestione mappe) **/
		this.mappaId = null
    }
    
    /**
     * Define the "instance" methods using the prototype and standard prototypal inheritance.
     */
	BasicMapOptions.prototype = {
    	getSourceProjection: function() { return( this.sourceProjection ); },
    	setSourceProjection: function(sourceProjection) { this.sourceProjection = sourceProjection; },
    	
    	getDestProjection: function() { return( this.destProjection ); },
    	setDestProjection: function(destProjection) { this.destProjection = destProjection; },
    	
    	getExtent: function() { return( this.extent ); },
    	setExtent: function(extent) { this.extent = extent; },
    	
    	getCenter: function() { return( this.center ); },
    	setCenter: function(center) { this.center = center; },
    	
    	getTargetMap: function() { return( this.targetMap ); },
    	setTargetMap: function(targetMap) { this.targetMap = targetMap; },
    	
    	getTreeUrl: function() { return( this.treeUrl ); },
    	setTreeUrl: function(treeUrl) { return( this.treeUrl = treeUrl); },
    	
    	getLayerUrl: function() { return( this.layerUrl ); },
    	setLayerUrl: function(layerUrl) { this.layerUrl = layerUrl; },
    	
    	getLayerStyleUrl: function() { return( this.layerStyleUrl ); },
    	setLayerStyleUrl: function(layerStyleUrl) { this.layerStyleUrl = layerStyleUrl; },
    	
    	getBasicLayers: function() { return( this.basicLayers ); },
    	setBasicLayers: function(basicLayers) { this.basicLayers = basicLayers; },
    	
    	getZoom: function() { return( this.zoom ); },
    	setZoom: function(zoom) { this.zoom = zoom; },
    	
    	getMinZoom: function() { return( this.minZoom ); },
    	setMinZoom: function(minZoom) { this.minZoom = minZoom; },
    	
    	getMaxZoom: function() { return( this.maxZoom ); },
    	setMaxZoom: function(maxZoom) { this.maxZoom = maxZoom; },
    	
    	getMinResolution: function() { return( this.minResolution ); },
    	setMinResolution: function(minResolution) { this.minResolution = minResolution; },
    	
    	getMaxResolution: function() { return( this.maxResolution ); },
    	setMaxResolution: function(maxResolution) { this.maxResolution = maxResolution; },
    	
    	getGeolocateZoom: function() { return( this.geolocateZoom ); },
    	setGeolocateZoom: function(geolocateZoom) { this.geolocateZoom = geolocateZoom; },
    	
    	isEnableAttribution: function() { return( this.enableAttribution ); },
    	setEnableAttribution: function(enableAttribution) { this.enableAttribution = enableAttribution; },
    	
    	isEnableRotation: function() { return( this.enableRotation ); },
    	setEnableRotation: function(enableRotation) { this.enableRotation = enableRotation; },
    	
    	isEnableZoom: function() { return( this.enableZoom ); },
    	setEnableZoom: function(enableZoom) { this.enableZoom = enableZoom; },
    	
    	isEnableFullscreen: function() { return( this.enableFullscreen ); },
    	setEnableFullscreen: function(enableFullscreen) { this.enableFullscreen = enableFullscreen; },
    	
    	isEnableMousePosition: function() { return( this.enableMousePosition ); },
    	setEnableMousePosition: function(enableMousePosition) { this.enableMousePosition = enableMousePosition; },
    	
    	isEnableZoomSlider: function() { return( this.enableZoomSlider ); },
    	setEnableZoomSlider: function(enableZoomSlider) { this.enableZoomSlider = enableZoomSlider; },
    	
    	isEnableZoomToExtent: function() { return( this.enableZoomToExtent ); },
    	setEnableZoomToExtent: function(enableZoomToExtent) { this.enableZoomToExtent = enableZoomToExtent; },
    	
    	isEnableLayerSwitcher: function() { return( this.enableLayerSwitcher ); },
    	setEnableLayerSwitcher: function(enableLayerSwitcher) { this.enableLayerSwitcher = enableLayerSwitcher; },
    	
    	isEnable3D: function() { return( this.enable3D ); },
    	setEnable3D: function(enable3D) { this.enable3D = enable3D; },
    	
    	isEnableLayersTree: function() { return( this.enableLayersTree ); },
    	setEnableLayersTree: function(enableLayersTree) { this.enableLayersTree = enableLayersTree; },
    	
    	isEnableGeolocation: function() { return( this.enableGeolocation ); },
    	setEnableGeolocation: function(enableGeolocation) { this.enableGeolocation = enableGeolocation; },
    	
    	isEnableOverviewMap: function() { return( this.enableOverviewMap ); },
    	setEnableOverviewMap: function(enableOverviewMap) { this.enableOverviewMap = enableOverviewMap; },
    	
    	isEnableScaleLine: function() { return( this.enableScaleLine ); },
    	setEnableScaleLine: function(enableScaleLine) { return( this.enableScaleLine = enableScaleLine); },
    	
    	isEnableMeasureLength: function() { return( this.enableMeasureLength ); },
    	setEnableMeasureLength: function(enableMeasureLength) { this.enableMeasureLength = enableMeasureLength; },
    	
    	isEnableMeasureArea: function() { return( this.enableMeasureArea ); },
    	setEnableMeasureArea: function(enableMeasureArea) { this.enableMeasureArea = enableMeasureArea; },
    	
    	isEnableMeasureAzimut: function() { return( this.enableMeasureAzimut ); },
    	setEnableMeasureAzimut: function(enableMeasureAzimut) { this.enableMeasureAzimut = enableMeasureAzimut; },
    	
    	isEnableDrawGeometry: function() { return( this.enableDrawGeometry ); },
    	setEnableDrawGeometry: function(enableDrawGeometry) { this.enableDrawGeometry = enableDrawGeometry; },
    	
    	getFullscreenSourceId: function() { return( this.fullscreenSourceId ); },
    	setFullscreenSourceId: function(fullscreenSourceId) { this.fullscreenSourceId = fullscreenSourceId; },
    	
    	getControlTargetId: function() { return( this.controlTargetId ); },
    	setControlTargetId: function(controlTargetId) { this.controlTargetId = controlTargetId; },
    	
    	getAdvancedControlHasLabel: function() { return( this.advancedControlHasLabel ); },
    	setAdvancedControlHasLabel: function(advancedControlHasLabel) { this.advancedControlHasLabel = advancedControlHasLabel; },
    	
    	getGeometryType: function() { return( this.geometryType ); },
    	setGeometryType: function(geometryType) { this.geometryType = geometryType; },

    	getSaveGeometryCallback: function() { return( this.saveGeometryCallback ); },
    	setSaveGeometryCallback: function(saveGeometryCallback) { this.saveGeometryCallback = saveGeometryCallback; },
    	
    	getCancelGeometryCallback: function() { return( this.cancelGeometryCallback ); },
    	setCancelGeometryCallback: function(cancelGeometryCallback) { this.cancelGeometryCallback = cancelGeometryCallback; },
    	
    	getProfiloId: function() { return( this.profiloId ); },
    	setProfiloId: function(profiloId) { this.profiloId = profiloId; },
    	
    	getMappaId: function() { return( this.mappaId ); },
    	setMappaId: function(mappaId) { this.mappaId = mappaId; }
    };
	/**
	 * Return the constructor function
	 */
    return BasicMapOptions;
});

/** 
 * Model contenente le impostazioni di configurazione della mappa
 */
BootApplication.factory("MapOptions", function(BasicMapOptions) {
	
	/** 
	 * Define the constructor function. 
	 */
    MapOptions = function(settings) {
    	/** 
    	 * create our new custom object that reuse the original object constructor
    	 */
    	BasicMapOptions.apply(this, arguments);
    	/**
    	 * APIProperty: sourceProjection
    	 * La projection con la quale l'entità sono gestite.
    	 * {string}
    	 */
    	this.sourceProjection = angular.isDefined(settings) && angular.isDefined(settings.sourceProjection) ? settings.sourceProjection : this.sourceProjection;
    	/**
    	 * APIProperty: destProjection
    	 * La projection con la quale l'entità sono disegnate in mappa.
    	 * {string}
    	 */
    	this.destProjection = angular.isDefined(settings) && angular.isDefined(settings.destProjection) ? settings.destProjection : this.destProjection,
    	/**
    	 * APIProperty: extent
    	 * Nella misura in cui vincola il centro, in altre parole, il centro non può essere impostato fuori misura.
    	 * {Array.<number>} 
    	 */
    	this.extent = angular.isDefined(settings) && angular.isDefined(settings.extent) ? settings.extent : this.extent,
    	/**
    	 * APIProperty: center
    	 * Array[lon, lat] rappresentanti la coordinata sulla quale centrare la mappa.
    	 * {Array.<number>} 
    	 */
    	this.center = angular.isDefined(settings) && angular.isDefined(settings.center) ? settings.center : this.center,
    	/**
         * APIProperty: targetMap
         * Identificativo dell'elemento (div) in cui disegnare la mappa
         * {string}
         */
    	this.targetMap = angular.isDefined(settings) && angular.isDefined(settings.targetMap) ? settings.targetMap : this.targetMap,
    	 /**
         * APIProperty: treeUrl
         * Url del servizio che restituisce il json con il quale disegnare l'albero(Ctegoria e sottocategoria).
         * 
         * NOTA: 
         * L'url che mi aspetto prende come parametri d'ingresso l'id profilo e l'id mappa necessariamente.
         * In generale, questi parametri li passo all'url facendo il replace delle sequenti stringhe:
         *   - {value1} per l'id profilo.
         *   - {value2} per l'id mappa.
         * 
         * Es url: "/getTreeCategoria.json"
         * {String}
         */
    	this.treeUrl = angular.isDefined(settings) && angular.isDefined(settings.treeUrl) ? settings.treeUrl : this.treeUrl,
    	/**
         * APIProperty: layerUrl
         * Url del servizio che restituisce il json con l'elenco dei layer da aggiungere alla mappa.
         * {String}
         */
    	this.layerUrl = angular.isDefined(settings) && angular.isDefined(settings.layerUrl) ? settings.layerUrl : this.layersUrl,
    	/**
         * APIProperty: layerStyleUrl
         * Url del servizio che restituisce il json con l'elenco degli stili con cui rappresentare i layer su mappa.
         * {String}
         */
    	this.layerStyleUrl = angular.isDefined(settings) && angular.isDefined(settings.layerStyleUrl) ? settings.layerStyleUrl : this.layerStyleUrl,
    	/**
         * APIProperty: basicLayersOpt
         * Individua se e quali layer aggiungere di default alla mappa
         * {Object ClassBuilder.BasicLayerInfo}
         */
    	this.basicLayers = angular.isDefined(settings) && angular.isDefined(settings.basicLayers) ? settings.basicLayers : this.basicLayers,
    	/**
    	 * APIProperty: zoom
    	 * Livello di zoom utilizzato per calcolare la risoluzione iniziale per la visualizzazione. 
    	 * {intero}
    	 */	
    	this.zoom = angular.isDefined(settings) && angular.isDefined(settings.zoom) ? settings.zoom : this.zoom,
    	/**
         * APIProperty: minZoom
         * Il livello di zoom minimo utilizzato.
         * {intero}
         */	
    	this.minZoom = angular.isDefined(settings) && angular.isDefined(settings.minZoom) ? settings.minZoom : this.minZoom,
    	/**
         * APIProperty: maxZoom
         * Il livello di zoom massimo utilizzato.
         * {intero}
         */	
    	this.maxZoom = angular.isDefined(settings) && angular.isDefined(settings.maxZoom) ? settings.maxZoom : this.maxZoom,
    	/**
    	 * APIProperty: minResolution
    	 * Risoluzione minima.
    	 * {number}
    	 */	
//    	this.minResolution = angular.isDefined(settings.minResolution) ? settings.minResolution : this.minResolution,
    	/**
    	 * APIProperty: maxResolution
    	 * Risoluzione massima.
    	 * {number}
    	 */	
//    	this.maxResolution = angular.isDefined(settings.maxResolution) ? settings.maxResolution : this.maxResolution,
    	/**
    	 * APIProperty: geolocateZoom
    	 * Indica il livello di zoom al quale portare la mappa quando viene geolocalizzata la posizione dell'utente. 
    	 * {intero}
    	 */	
    	this.geolocateZoom = angular.isDefined(settings) && angular.isDefined(settings.geolocateZoom) ? settings.geolocateZoom : this.geolocateZoom,				
    	/**
    	 * APIProperty: enableAttribution
    	 * Opzione per mostrare tutti gli attributi associati con le fonti di livello nella mappa. 
    	 * Di default è visualizzato nella parte in basso a destra della mappa.
    	 * {boolean}
    	 */
    	this.enableAttribution = angular.isDefined(settings) && angular.isDefined(settings.enableAttribution) ? settings.enableAttribution : this.enableAttribution,
    	/**
    	 * APIProperty: enableRotation
    	 * Opzione per abilitare la rotazione della mappa e il pulsante per ripristinare la rotazione a 0. 
    	 * {boolean} 
    	 */
    	this.enableRotation = angular.isDefined(settings) && angular.isDefined(settings.enableRotation) ? settings.enableRotation : this.enableRotation,
    	/**
    	 * APIProperty: enableZoom
    	 * Opzione per abilitare lo zoom in e lo zoom out. 
    	 * {boolean}
    	 */
    	this.enableZoom = angular.isDefined(settings) && angular.isDefined(settings.enableZoom) ? settings.enableZoom : this.enableZoom,
    	/**
    	 * APIProperty: enableFullscreen
    	 * Opzione che fornisce un pulsante per attivare o disattivare la mappa in modalità a schermo intero.
    	 * {boolean} Il valore predefinito è false. 
    	 */
    	this.enableFullscreen = angular.isDefined(settings) && angular.isDefined(settings.enableFullscreen) ? settings.enableFullscreen : this.enableFullscreen,
    	/**
    	 * APIProperty: enableMousePosition
    	 * Un controllo per mostrare le coordinate 2D del cursore del mouse. Per default, queste sono nella proiezione definita nella
    	 * proprietà "sourceProjection" di questo oggetto.  
    	 * {boolean}
    	 */
    	this.enableMousePosition = angular.isDefined(settings) && angular.isDefined(settings.enableMousePosition) ? settings.enableMousePosition : this.enableMousePosition,
    	/**
    	 * APIProperty: enableZoomSlider
    	 * Un controllo con 2 pulsanti, uno per lo zoom in e una per lo zoom out e lo slider centrale per spostarsi direttamente 
    	 * ad un certo livello di zoom.
    	 * {boolean}
    	 */
    	this.enableZoomSlider = angular.isDefined(settings) && angular.isDefined(settings.enableZoomSlider) ? settings.enableZoomSlider : this.enableZoomSlider,
    	/**
    	 * APIProperty: enableZoomToExtent
    	 * Un controllo pulsante che, se premuto, cambia la visualizzazione della mappa in misura specifica. 
    	 * {boolean}
    	 */
    	this.enableZoomToExtent = angular.isDefined(settings) && angular.isDefined(settings.enableZoomToExtent) ? settings.enableZoomToExtent : this.enableZoomToExtent,
    	/**
    	 * APIProperty: enable3D
    	 * Un controllo pulsante che, se premuto, attiva/disattiva la visualizzazione della mappa in 3D/2D. 
    	 * {boolean}
    	 */
    	this.enable3D = angular.isDefined(settings) && angular.isDefined(settings.enable3D) ? settings.enable3D : this.enable3D,
    	/**
         * APIProperty: enableLayersTree
         * Un controllo pulsante che, se premuto, crea e attiva/disattiva la visualizzazione dell'albero dei layer
         * {boolean}
         */
    	this.enableLayersTree = angular.isDefined(settings) && angular.isDefined(settings.enableLayersTree) ? settings.enableLayersTree : this.enableLayersTree,
    	/**
    	 * APIProperty: enableGeolocation
    	 * Un controllo pulsante che, se premuto, viene individuata la posizione di un utente.
    	 * {boolean}
    	 */
    	this.enableGeolocation = angular.isDefined(settings) && angular.isDefined(settings.enableGeolocation) ? settings.enableGeolocation : this.enableGeolocation,
    	/**
    	 * APIProperty: enableOverviewMap
    	 * Creare un nuovo controllo con una mappa in qualità di una mappa panoramica per un'altra mappa definita.
    	 * {boolean}
    	 */
    	this.enableOverviewMap = angular.isDefined(settings) && angular.isDefined(settings.enableOverviewMap) ? settings.enableOverviewMap : this.enableOverviewMap,
    	/**
    	 * APIProperty: enableScaleLine
    	 * Un controllo che visualizza distanze x assi grezze, calcolato per il centro della finestra.
    	 * {boolean}
    	 */
    	this.enableScaleLine = angular.isDefined(settings) && angular.isDefined(settings.enableScaleLine) ? settings.enableScaleLine : this.enableScaleLine,
    	/**
    	 * APIProperty: enableMeasureLength
    	 * Un controllo che attiva/disattiva lo strumento per disegnare su mappa e misurare la lunghezza dell'arco tracciato.
    	 * NOTA: la misura avviene prendendo in considerazione la curvatura terrestre
    	 * {boolean}
    	 */
    	this.enableMeasureLength = angular.isDefined(settings) && angular.isDefined(settings.enableMeasureLength) ? settings.enableMeasureLength : this.enableMeasureLength,
    	/**
    	 * APIProperty: enableMeasureArea
    	 * Un controllo che attiva/disattiva lo strumento per disegnare su mappa un poligono e misurarne la grandezza della superficie.
    	 * NOTA: la misura avviene prendendo in considerazione la curvatura terrestre
    	 * {boolean}
    	 */
    	this.enableMeasureArea = angular.isDefined(settings) && angular.isDefined(settings.enableMeasureArea) ? settings.enableMeasureArea : this.enableMeasureArea,
    	/**
    	 * APIProperty: enableMeasureAzimut
    	 * Un controllo per misurare l'angolo del cerchio tracciato e la larghezza del diametro.
    	 * {boolean}
    	 */
    	this.enableMeasureAzimut = angular.isDefined(settings) && angular.isDefined(settings.enableMeasureAzimut) ? settings.enableMeasureAzimut : this.enableMeasureAzimut,
    	/** 
    	 * Il controllo LayerSwitcher visualizza una tabella di contenuti per la mappa. In questo modo l'utente può per i layer di Base passare da un
    	 * BaseLayers ad un'altro.
    	 * Mentre, per i layer non di base, mostrare o nascondere i livelli e consentirne il riordino. 
    	 * Per impostazione predefinita, lo switcher è mostrato minimizzato sul bordo destro della mappa, l'utente può espandere cliccando sulla maniglia.
    	 */
    	this.enableLayerSwitcher = angular.isDefined(settings) && angular.isDefined(settings.enableLayerSwitcher) ? settings.enableLayerSwitcher : this.enableLayerSwitcher,
    	/**
    	 * APIProperty: geometryType
    	 * Array contenente le tipologie di geometrie che si possono disegnare e modificare sulla mappa 
    	 * {String[]}
    	 */
    	this.geometryType = angular.isDefined(settings) && angular.isDefined(settings.geometryType) ? settings.geometryType : this.geometryType,
    	/**
    	 * APIProperty: enableDrawGeometry
    	 * Un controllo per disegnare la geometria di punti, linestring e poligoni sulla mappa
    	 * {boolean}
    	 */
    	this.enableDrawGeometry = angular.isDefined(settings) && angular.isDefined(settings.enableDrawGeometry) ? settings.enableDrawGeometry : this.enableDrawGeometry,
    	/** 
    	 * Identificativo dell'elemento da visualizzare a schermo intero. Quando non è previsto, sarà l'elemento che contiene la mappa viewport 
    	 * ad essere visualizzato a schermo intero. 
    	 * {String}
    	 */
    	this.fullscreenSourceId = angular.isDefined(settings) && angular.isDefined(settings.fullscreenSourceId) ? settings.fullscreenSourceId : this.fullscreenSourceId,
    	/** 
    	 * Identificativo dell'elemento HTML in cui openalyer inserirà i controlli che la libreria mette a disposizione. 
    	 * (Es: zoomExtent, fullscreen, 3D, geoLocate, measureLength, measureArea, measureAzimut )
    	 * {String}
    	 */
    	this.controlTargetId = angular.isDefined(settings) && angular.isDefined(settings.controlTargetId) ? settings.controlTargetId : this.controlTargetId,
    	/**
    	 * Determina se aggiungere ai controlli di Openlayer oltre l'icona, già prevista, anche una label testuale.
    	 * (Es: zoomExtent, fullscreen, 3D, geoLocate, measureLength, measureArea, measureAzimut )
    	 * {Boolean}
    	 */
    	this.advancedControlHasLabel = angular.isDefined(settings) && angular.isDefined(settings.advancedControlHasLabel) ? settings.advancedControlHasLabel : this.advancedControlHasLabel,
    	/**
    	 * APIProperty: saveGeometryCallback
    	 * Funzione di callback richiamata alla pressione del tasto Salva della geometria disegnata
    	 * {String}
    	 */
    	this.saveGeometryCallback = angular.isDefined(settings) && angular.isDefined(settings.saveGeometryCallback) ? settings.saveGeometryCallback : this.saveGeometryCallback,
    	/**
    	 * APIProperty: cancelGeometryCallback
    	 * Funzione di callback richiamata alla pressione del tasto Cancella della geometria disegnata
    	 * {String}
    	 */
    	this.cancelGeometryCallback = angular.isDefined(settings) && angular.isDefined(settings.cancelGeometryCallback) ? settings.cancelGeometryCallback : this.cancelGeometryCallback,
    	/**
    	 * APIProperty: profiloId
    	 * Identificativo della mappa (Entrambi determinabili consultando l'interfaccia di gestione mappe)
    	 * {Integer}
    	 */
    	this.mappaId = angular.isDefined(settings) && angular.isDefined(settings.mappaId) ? settings.mappaId : this.mappaId,
    	/**
    	 * APIProperty: mappaId
    	 * Identificativo del profilo della mappa (Entrambi determinabili consultando l'interfaccia di gestione mappe).
    	 * {Integer}
    	 */
    	this.profiloId = angular.isDefined(settings) && angular.isDefined(settings.profiloId) ? settings.profiloId : this.profiloId
    }
    
	/** 
	 * reuse the original object prototype
	 */
	MapOptions.prototype = new BasicMapOptions();
	/**
	 * Return the constructor function
	 */
	return MapOptions;
});

/** 
 * Model dove salvare le instanze delle mappe 2D e/o 3D dopo che sono state costuite nel service.
 */
BootApplication.factory("olMapsInst", function() {
	
	/** 
	 * Define the constructor function. 
	 */
    function olMapsInst() {
    	this.map2DInstance = null;
    	this.map3DInstance = null;
    }
    
    /**
     * Define the "instance" methods using the prototype and standard prototypal inheritance.
     */
    olMapsInst.prototype = {
    	getMap2DInstance: function() { return( this.map2DInstance ); },
    	setMap2DInstance: function(map2DInstance) { this.map2DInstance = map2DInstance; },
    	
    	getMap3DInstance: function() { return( this.map3DInstance ); },
    	setMap3DInstance: function(map3DInstance) { this.map3DInstance = map3DInstance; },
    };
    
    /**
	 * Return the constructor function
	 */
    return olMapsInst;
});

/** 
 * Model dove salvare i dati utili al build dell'albero dei layer dopo che sono state costuite nel service.
 * 
 *  - "treeControl": controllo per di openlayers per "Mostrare e nascondere l'albero".
 *  - "treeConfig": l'oggetto di configurazione del JsTree
 *  - "treeData": l'array con gli elementi della struttura
 */
BootApplication.factory("olTreeInst", function() {
	
	/** 
	 * Define the constructor function. 
	 */
    function olTreeInst() {
    	this.treeControl = null;
    	this.treeConfig = null;
    	this.treeData = null;
    	this.treeLayers = null;
    	this.treeStyles = null;
    }
    
    /**
     * Define the "instance" methods using the prototype and standard prototypal inheritance.
     */
    olTreeInst.prototype = {
    	getTreeControl: function() { return( this.treeControl ); },
    	setTreeControl: function(treeControl) { this.treeControl = treeControl; },
    	
    	getTreeConfig: function() { return( this.treeConfig ); },
    	setTreeConfig: function(treeConfig) { this.treeConfig = treeConfig; },
    	
    	getTreeData: function() { return( this.treeData ); },
    	setTreeData: function(treeData) { this.treeData = treeData; },
    	
    	getTreeLayers: function() { return( this.treeLayers ); },
    	setTreeLayers: function(treeLayers) { this.treeLayers = treeLayers; },
    	
    	getTreeStyles: function() { return( this.treeStyles ); },
    	setTreeStyles: function(treeStyles) { this.treeStyles = treeStyles; }
    };
    
    /**
	 * Return the constructor function
	 */
    return olTreeInst;
});


